package aash.catalog.controller;

import java.util.Properties;

import org.apache.log4j.Logger;

import aash.catalog.models.CatalogModel;
import aash.catalog.views.AbstractView;
import aash.catalog.views.MainView;
import aash.catalog.views.NewDbView;
import aash.catalog.views.OpenDbView;

/**
 * ExplorerView Controller for MVC.
 * @author Aashintan
 */
public class CatalogController {
    /**
     * Logger.
     */
    private static Logger log = Logger.getLogger(CatalogController.class.getName());
    /**
     * The MVC Model.
     */
    private CatalogModel model = null;
    /**
     * Explorer View.
     */
    private AbstractView mainView = null;
    /**
     * OpenDb View.
     */
    private AbstractView openDbView = null;
    /**
     * NewDb View.
     */
    private AbstractView newDbView = null;
    /**
     * Properties file.
     */
    private Properties prop = null;
    /**
     * Path to xml properties file.
     */
    private String propertiesPath = "config/config.xml";

    /**
     * Class constructor.
     * @param mModel the Controller associated Model
     */
    public CatalogController(final CatalogModel mModel) {
        model = mModel;
        mainView = new MainView(this, "Explorer", model.getLines(), model.getFields());
        addListenersToModel();
    }

    /**
     * Close actions.
     */
    public final void close() {
        model.closeDB();
    }

    /**
     * Close view.
     */
    public final void closeView() {
        mainView.close();
    }

    /**
     * Display main view.
     */
    public final void displayMainView() {
        mainView.display();
    }

    /**
     * @return the list of DB available.
     */
    public final String[] getDbList() {
        String[] dbList = model.getDbList();
        return dbList;
    }

    /**
     * Initiate the application.
     */
    public final void init() {
    	model.initDbDirectory();
        // Loading properties file
        prop = model.loadPropertiesFromXMLFile(propertiesPath);
        if ("true".equals(prop.getProperty("database.open"))) {
            String dbName = prop.getProperty("database.open.name");
            int id = Integer.parseInt(prop.getProperty("database.open.id"));
            // Connect DB
            model.connectDB(dbName);
            // Place current id
            model.setID(id);
        }
    }

    /**
     * Notify action close DB.
     */
    public final void notifyCloseDB() {
        model.closeDB();
        updateProperties();
    }

    /**
     * Notify when the backward element is asked.
     */
    public final void notifyListBackward() {
        model.listBackward();
    }

    /**
     * Notify when the forward element is asked.
     */
    public final void notifyListForward() {
        model.listForward();
    }

    /**
     * Notify action new DB.
     * @param stName of the DB.
     */
    public final void notifyNewDb(final String stName) {
        log.info("notify new DB : " + stName + ".");
        model.openDB(stName);
        model.formatDb();
        String toAppend = prop.getProperty("database.list");
        if (!"".equals(toAppend)) {
            toAppend = toAppend + ", ";
        }
        toAppend = toAppend + stName;
        prop.setProperty("database.list", toAppend);
        updateProperties();
    }

    /**
     * Notify action new DB view.
     */
    public final void notifyNewDbView() {
        log.info("notify new DB view.");
        if (newDbView == null) {
            newDbView = new NewDbView(this);
        }
        newDbView.display();
    }

    /**
     * Notify action open DB.
     * @param stName of the DB.
     */
    public final void notifyOpenDb(final String stName) {
        log.info("notify open DB : " + stName + ".");
        model.closeDB();
        model.connectDB(stName);
        updateProperties();
    }

    /**
     * Notify action open DB view.
     */
    public final void notifyOpenDbView() {
        log.info("notify open DB view.");
        if (openDbView == null) {
            openDbView = new OpenDbView(this);
        } else {
        	((OpenDbView)openDbView).refreshDbList();
        }
        openDbView.display();
    }

    /**
     * Notify when a property is changed.
     * @param stKey of the property
     * @param stValue of the property
     */
    public final void notifyPropertyChanged(final String stKey, final String stValue) {
        model.setProperty(stKey, stValue);
    }

    /**
     * Notify when save button is clicked.
     * @param stAttr list of values to save
     */
    public final void notifySave(final String[] stAttr) {
        if (model.isDBconnected()) {
            log.info("Save notified with value :" + stAttr[0] + ", " + stAttr[1] + ", " + stAttr[2] + ", "
                + stAttr[3] + ", " + stAttr[4] + ".");
            model.save(stAttr);
            updateProperties();
        }
    }

    /**
     * Update the main view.
     */
    public final void updateMainView() {
        ((MainView) mainView).repaint();
    }

    /**
     * Add listeners to Model.
     */
    private void addListenersToModel() {
        model.addExplorerListener((MainView) mainView);
    }

    /**
     * Update properties file.
     */
    private void updateProperties() {
        if (model.isDBconnected()) {
            prop.setProperty("database.open", "true");
            String dbName = model.getDbName();
            prop.setProperty("database.open.name", dbName);
            Integer id = model.getId();
            prop.setProperty("database.open.id", id.toString());
        } else {
            prop.setProperty("database.open", "false");
            prop.setProperty("database.open.name", "");
            prop.setProperty("database.open.id", "");
        }
        model.storePropertiesToXMLFile(prop, propertiesPath);
    }
}
